#pragma once
#include <time.h>
#include "FCB.h"
#include "../util/Tools.h"
#include "Constants.h"

// Inode最多占64位
typedef struct Inode {
    short parent, leftmostChild, rightSibling; // 均指向FCB
    short directBlocks[DIRECT_BLOCK_SIZE];
    short indirectBlock; // 间接块地址第一位如果是1则为目录
    int fileSize; // 单位为KB?
    time_t createTime;
    time_t lastModifiedTime;
    char status;
    char padding[15]; // 手动对齐填充
} Inode;

static short InodeList_createInode(Inode inodeList[], int fileSize, int currentDirectory, Boolean isDir) {
    Inode *entry = NULL;
    short i = 0;
    for (; i < INODE_LIST_SIZE; i++) {
        entry = inodeList + i;
        if (entry->status == 0) {
            break;
        }
    }
    EXIT_IF_NULL(entry, "无可用Inode")

    entry->status = 1;
    entry->fileSize = fileSize;
    entry->parent = (short) currentDirectory;
    entry->leftmostChild = NOTHING;
    entry->rightSibling = NOTHING;
    time(&entry->createTime);
    entry->lastModifiedTime = entry->createTime;
    if (isDir) {
        entry->indirectBlock = (short) 0x8000;
    }

    return i;
}

static void Inode_print(Inode* inode) {
    char *fileType = inode->indirectBlock < 0 ? "Dir" : "File";
    printf("%s parent:%d size:%d indirectBlock:0x%hx\n", fileType,
           inode->parent, inode->fileSize, inode->indirectBlock);
    printf("create time: %ld\n", inode->createTime);
    printf("directBlock:\n");
    for (int i = 0; i < DIRECT_BLOCK_SIZE; ++i) {
        printf("%d ", inode->directBlocks[i]);
    }
    putchar('\n');
}

static void Inode_addChild(FCB fcbList[], Inode inodeList[], Inode *inode, short childFCBPtr) {
    if (inode->leftmostChild == NOTHING) {
        inode->leftmostChild = childFCBPtr;
        return;
    }
    inode = inodeList + fcbList[inode->leftmostChild].inodeNumber;
    while (inode->rightSibling != NOTHING) {
        inode = inodeList + fcbList[inode->rightSibling].inodeNumber;
    }
    inode->rightSibling = childFCBPtr;
}

static void Inode_deleteChild(FCB fcbList[], Inode inodeList[], Inode *dirInode, short childFCBPtr) {
    if (dirInode->leftmostChild == childFCBPtr) { // 要删除的文件是目录的第一个孩子
        dirInode->leftmostChild = inodeList[fcbList[childFCBPtr].inodeNumber].rightSibling;
    } else { // 不是第一个孩子
        int currentFCBPtr = dirInode->leftmostChild;
        FCB *currentFCB = fcbList + currentFCBPtr;
        Inode *currentInode = inodeList + currentFCB->inodeNumber;
        while (True) {
            if (currentInode->rightSibling == childFCBPtr) {
                short nextFCBPtr = inodeList[fcbList[childFCBPtr].inodeNumber].rightSibling;
                currentInode->rightSibling = nextFCBPtr;
                break;
            }
            currentFCBPtr = currentInode->rightSibling;
            currentFCB = fcbList + currentFCBPtr;
            currentInode = inodeList + currentFCB->inodeNumber;
        }
    }
}